package xml.uidElements;

import java.util.ArrayList;
import java.util.List;

import xml.others.UIDException;
import xml.uidElements.entry.AbstractDataItem;
import xml.uidElements.entry.AbstractStructure;
import xml.uidElements.entry.DataEntry;
import xml.uidElements.entry.EnumeratedData;
import xml.uidElements.entry.ORDataEntry;
import xml.uidElements.entry.XORDataEntry;
import xml.uidElements.output.AbstractOutputDataItem;
import xml.uidElements.output.AbstractOutputStructure;
import xml.uidElements.output.DataOutput;
import xml.uidElements.output.OutputDataItem;
import xml.uidElements.output.OutputDataItemSet;
import xml.uidElements.output.OutputStructure;
import xml.uidElements.output.OutputStructureSet;

public abstract class AbstractState {

	protected String id;
	protected List<UIDNewElement> listElements;
	protected List<Transition> listOutgoingTransitions;

	public AbstractState(String id) {
		this.id = id;
	}

	public void insertInputDataItem(AbstractDataItem dataItem) {

		if (listElements == null) {
			this.listElements = new ArrayList<UIDNewElement>();
		}

		for (int i = 0; i < this.listElements.size(); i++) {
			UIDNewElement elem = this.listElements.get(i);
			if (elem instanceof DataEntry
					&& ((DataEntry) elem).getName().equals(dataItem.getName()))
				throw new UIDException(UIDException.EXISTING_DATA_ITEM,
						"There is already a data item with this name");
		}
		listElements.add(new DataEntry(dataItem));

	}

	public void insertInputStructure(AbstractStructure structure) {
		if (listElements == null) {
			this.listElements = new ArrayList<UIDNewElement>();
		}

		for (int i = 0; i < this.listElements.size(); i++) {
			UIDNewElement elem = this.listElements.get(i);
			if (elem instanceof DataEntry
					&& ((DataEntry) elem).getName().equals(structure.getName()))
				throw new UIDException(UIDException.EXISTING_STRUCTURE,
						"There is already a structure with this name");
		}
		listElements.add(new DataEntry(structure));

	}

	public String getId() {
		return this.id;
	}

	public void setId(String id) {
		this.id = id;
	}

	public void insertOutputDataItem(AbstractOutputDataItem dataItem) {
		if (listElements == null) {
			this.listElements = new ArrayList<UIDNewElement>();
		}

		for (int i = 0; i < this.listElements.size(); i++) {
			UIDNewElement elem = this.listElements.get(i);
			if (elem instanceof DataOutput
					&& ((DataOutput) elem).getName().equals(dataItem.getName()))
				throw new UIDException(UIDException.EXISTING_DATA_ITEM,
						"There is already a data item with this name");
		}
		listElements.add(new DataOutput(dataItem));

	}

	public void insertOutputStructure(AbstractOutputStructure structure) {

		if (listElements == null) {
			this.listElements = new ArrayList<UIDNewElement>();
		}

		for (int i = 0; i < this.listElements.size(); i++) {
			UIDNewElement elem = this.listElements.get(i);
			if (elem instanceof DataOutput
					&& ((DataOutput) elem).getName()
							.equals(structure.getName()))
				throw new UIDException(UIDException.EXISTING_STRUCTURE,
						"There is already a structure with this name");
		}
		listElements.add(new DataOutput(structure));

	}

	public void insertInputEnumeratedData(EnumeratedData enumeratedData) {

		if (listElements == null) {
			this.listElements = new ArrayList<UIDNewElement>();
		}

		for (int i = 0; i < this.listElements.size(); i++) {
			UIDNewElement elem = this.listElements.get(i);
			if (elem instanceof DataEntry
					&& ((DataEntry) elem).getName().equals(
							enumeratedData.getName()))
				throw new UIDException(UIDException.EXISTING_STRUCTURE,
						"There is already a structure with this name");
		}
		listElements.add(new DataEntry(enumeratedData));

	}

	public void insertInputORDataEntry(ORDataEntry orDataEntry) {

		if (listElements == null) {
			this.listElements = new ArrayList<UIDNewElement>();
		}

		for (int i = 0; i < this.listElements.size(); i++) {
			UIDNewElement elem = this.listElements.get(i);
			if (elem instanceof DataEntry
					&& ((DataEntry) elem).getName().equals(
							orDataEntry.getName()))
				throw new UIDException(UIDException.EXISTING_STRUCTURE,
						"There is already a structure with this name");
		}
		listElements.add(new DataEntry(orDataEntry));

	}

	public void insertInputXORDataEntry(XORDataEntry xorDataEntry) {

		if (listElements == null) {
			this.listElements = new ArrayList<UIDNewElement>();
		}

		for (int i = 0; i < this.listElements.size(); i++) {
			UIDNewElement elem = this.listElements.get(i);
			if (elem instanceof DataEntry
					&& ((DataEntry) elem).getName().equals(
							xorDataEntry.getName()))
				throw new UIDException(UIDException.EXISTING_STRUCTURE,
						"There is already a structure with this name");
		}
		listElements.add(new DataEntry(xorDataEntry));

	}

	public void insertText(Text text) {

		if (listElements == null) {
			this.listElements = new ArrayList<UIDNewElement>();
		}

		for (int i = 0; i < this.listElements.size(); i++) {
			UIDNewElement elem = this.listElements.get(i);
			if (elem instanceof Text
					&& ((Text) elem).getId().equals(text.getId()))
				throw new UIDException(UIDException.EXISTING_STRUCTURE,
						"There is already a text with this name");
		}
		listElements.add(text);

	}

	public void insertOutgoingTransition(Transition transition) {

		if (listOutgoingTransitions == null)
			listOutgoingTransitions = new ArrayList<Transition>();

		for (int i = 0; i < this.listOutgoingTransitions.size(); i++) {
			Transition trans = this.listOutgoingTransitions.get(i);
			if (trans.getId().equals(transition.getId()))
				throw new UIDException(UIDException.EXISTING_TRANSITION,
						"There is already a transition with this id");
		}
		listOutgoingTransitions.add(transition);

	}

	public void insertTransitionFromDataItem(String idSourceDataItem,
			Transition transition) {

		if (listElements == null) {
			throw new UIDException(UIDException.NOT_EXISTING_DATA_ITEM, "");
		}

		for (int i = 0; i < this.listElements.size(); i++) {
			UIDNewElement elem = this.listElements.get(i);

			if (elem instanceof DataOutput
					&& ((DataOutput) elem).getName().equals(idSourceDataItem)) {

				((OutputDataItem) ((DataOutput) elem).getElement())
						.insertOutgoingTransition(transition);
				return;
			}
		}
		throw new UIDException(UIDException.NOT_EXISTING_DATA_ITEM, "");

	}

	public void insertTransitionFromStructure(String idSourceStructure,
			Transition transition) {

		if (listElements == null) {
			throw new UIDException(UIDException.NOT_EXISTING_STRUCTURE, "");
		}

		for (int i = 0; i < this.listElements.size(); i++) {
			UIDNewElement elem = this.listElements.get(i);

			if (elem instanceof DataOutput
					&& ((DataOutput) elem).getName().equals(idSourceStructure)) {

				((OutputStructure) ((DataOutput) elem).getElement())
						.insertOutgoingTransition(transition);
				return;
			}

		}
		throw new UIDException(UIDException.NOT_EXISTING_STRUCTURE, "");
	}

	public void insertTransitionFromSetDataItem(String idSourceDataItem,
			TransitionFromSet transition) {

		if (listElements == null) {
			throw new UIDException(UIDException.NOT_EXISTING_DATA_ITEM, "");
		}

		for (int i = 0; i < this.listElements.size(); i++) {
			UIDNewElement elem = this.listElements.get(i);

			if (elem instanceof DataOutput
					&& ((DataOutput) elem).getName().equals(idSourceDataItem)) {

				((OutputDataItemSet) ((DataOutput) elem).getElement())
						.insertOutgoingTransition(transition);
				return;
			}
		}
		throw new UIDException(UIDException.NOT_EXISTING_DATA_ITEM, "");

	}

	public void insertTransitionFromSetStructure(String idSourceStructure,
			TransitionFromSet transition) {
		if (listElements == null) {
			throw new UIDException(UIDException.NOT_EXISTING_STRUCTURE, "");
		}

		for (int i = 0; i < this.listElements.size(); i++) {
			UIDNewElement elem = this.listElements.get(i);

			if (elem instanceof DataOutput
					&& ((DataOutput) elem).getName().equals(idSourceStructure)) {

				((OutputStructureSet) ((DataOutput) elem).getElement())
						.insertOutgoingTransition(transition);
				return;
			}

		}
		throw new UIDException(UIDException.NOT_EXISTING_STRUCTURE, "");

	}

	public List<UIDNewElement> getListElements() {
		return listElements;
	}

}